package pokerAI.PokerAI;

import java.io.*;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Stack;
import java.util.Random;
import java.lang.Math;
import java.lang.String;

class HandCompTest{
       
        public HandCompTest(){
               
        }
        public int handComp(Card[] passedIn) {
               
               
                int rating = 0;
                // 0 - 209 high card
                // 210 - 419 one pair
                // 420 - 629 two pair
                // 630 - 839 three of a kind
                // 840 - 1049 straight
                // 1050 - 1259 flush
                // 1260 - 1469 full house
                // 1470 - 1679 four of a kind
                // 1680 - 1889 straight flush
                // 2099 royal flush
               
                char flushSuit = 'z';
                int fourOfAKind = 0;
                int threeOfAKindA = 0;
                int threeOfAKindTemp = 0;
                int twoOfAKindA = 0;
                int twoOfAKindB = 0;
                int twoOfAKindTemp = 0;
                int swapKind = 0;
                int highCard = 0;
                int j=0;
               
                int cardPtr = 0;
                int straightCount = 1;  
                int initialCardValue;
               
                BigHand hand = new BigHand();
               
                int count = 0;
                for(int z = 0; z < passedIn.length; z++){
                        hand.receiveCard(passedIn[z]);
                        count++;
                }      
                Card filler = new Card( -2, 'x');
                while(count < 7){
                        hand.receiveCard(filler);
                        count++;
                }
               
                BigHand smallerHand = new BigHand();
                BigHand smallerHandB = new BigHand();
               
                /////////////////////////////////////////////////////////////////////////////////////
                // add -1 , f's to end ot make it 7 every time
                /////////////////////////////////////////////////////////////////////////////////////
               
                // bubble sort putting aces in frotn and decending from left to right
                int x;
                int temp;
                int temp2;
                Card tCard;
                boolean swaps = true;
                count = 0;
                while (swaps && count < 8){
                        swaps = false;
                        for(x = 0; x < 6; x++){
                                // if has extra condition to make sure Aces are at the end
                                temp = hand.viewCard(x).getNumber();
                                temp2 = hand.viewCard(x+1).getNumber();
                                if(temp == 1)
                                        temp = 14;
                                if(temp2 == 1)
                                        temp2 = 14;
                                // do bubbling  
                                if(temp < temp2){
                                        // swap elements
                                        swaps = true;
                                        tCard = hand.viewCard(x);
                                        hand.setCard(x, hand.viewCard(x+1));
                                        hand.setCard(x+1, tCard);
                                }
                        }
                        count++;
                }

               
                int suits[] = new int[4];       // will hold hte amount of time each suit is used
                suits[0] = 0;   // spades
                suits[1] = 0;   // diamonds
                suits[2] = 0;   // hearts
                suits[3] = 0;   // clubs
                for(j = 0; j < 7; j++){
                        // if cards suit is space increment space
                        if( hand.viewCard(j).getSuit() == 's')
                                suits[0] = suits[0] + 1;
                        else if( hand.viewCard(j).getSuit() == 'd')
                                suits[1] = suits[1] + 1;
                        else if( hand.viewCard(j).getSuit() == 'h')
                                suits[2] = suits[2] + 1;
                        else if( hand.viewCard(j).getSuit() == 'c')
                                suits[3] = suits[3] + 1;        
                }
               
       
               
                // royal flush and straight flush
               
                // find if any of hte suits had at least 5  cards (enough for a flush) (only one could have at least 5 bc theres only 7 tops)
                for(j=0; j<4; j++){
                        if( suits[j] >=5 ){
                                if(j == 0)
                                        flushSuit = 's';
                                if(j == 1)
                                        flushSuit = 'd';
                                if(j == 2)
                                        flushSuit = 'h';
                                if(j == 3)
                                        flushSuit = 'c';        
                        }
                }      
                /// if one of them was greater than 5 then we saved it as flush suit and thus it is not still z
                if(flushSuit != 'z'){
               
                        // remove all cards not in the flushsuit
                        x=0;
                        for (x = 0; x<7; x++){
                                if(hand.viewCard(x).getSuit() == flushSuit)
                                        smallerHand.receiveCard(hand.viewCard(x));
                        }
                               
                       
                        // royal flush
                        if( smallerHand.viewCard(0).getNumber() == 1 && smallerHand.viewCard(1).getNumber() == 13 && smallerHand.viewCard(2).getNumber() == 12
                                        && smallerHand.viewCard(3).getNumber() == 11 && smallerHand.viewCard(4).getNumber() == 10){
                                        rating = 2099;
                                        System.out.println("  Royal Flush  ");
                                        return rating;
                        }

                        // straight flush
                        // use a linked list .. run 14 times ,check if u can get 5 trues in a row (true for next card is one less), if true then straight flush
                        // also if false then keep track of the first card u get true for (so just any time false reset the first card poitner
                        count = 0;
                        cardPtr = 0;
                        straightCount = 1;      // count the first card
                        initialCardValue = smallerHand.viewCard(0).getNumber();
                        while(count < 14){
                                if(cardPtr < smallerHand.getAmountOfCards()-1){
                                        if(smallerHand.viewCard(cardPtr).getNumber() == smallerHand.viewCard(cardPtr+1).getNumber()+1
                                                        || smallerHand.viewCard(cardPtr).getNumber() == 1 && smallerHand.viewCard(cardPtr+1).getNumber() == 13)
                                                straightCount++;
                                        else{
                                                straightCount = 1;
                                                initialCardValue = smallerHand.viewCard(cardPtr+1).getNumber();
                                        }
                                        cardPtr++;
                                }      
                                else if(cardPtr == smallerHand.getAmountOfCards()-1){   // for if we are at the last card in the hand
                                        if(smallerHand.viewCard(cardPtr).getNumber() == 2 && smallerHand.viewCard(0).getNumber() == 1)
                                                straightCount++;
                                        else{
                                                straightCount = 1;
                                                initialCardValue = smallerHand.viewCard(0).getNumber();
                                        }      
                                        cardPtr=0;
                                }
                                if(straightCount == 5){
                                        // we have a straight flush
                                        rating = 1680 + ( 14 * initialCardValue);
                                        //////////////////////////////////////////////////////////////////////////////////////////
                                        ///////////// if we need the biggest card in teh straight to grade them then just check for that each time straight count is incremented
                                        ///////////////////////////////
                                        System.out.println("   Straight Flush  ");
                                        return rating;
                                }                              
                                count++;
                        }
                       
                }
               
               
               
               
                int[] cards = new int[14];      // will hold hte amount of time each suit is used
               
                cards[0] = 0;   // nothing
                cards[1] = 0;   // ace
                cards[2] = 0;   // two
                cards[3] = 0;   // three
                cards[4] = 0;   // ..
                cards[5] = 0;
                cards[6] = 0;
                cards[7] = 0;
                cards[8] = 0;
                cards[9] = 0;
                cards[10] = 0;
                cards[11] = 0;
                cards[12] = 0;  // ...
                cards[13] = 0;  // king
               
                for(j = 0; j < 7; j++){
                        // if cards suit is space increment space
                        if( hand.viewCard(j).getNumber() == 1)
                                cards[1] = cards[1] + 1;
                        else if( hand.viewCard(j).getNumber() == 2)
                                cards[2] = cards[2] + 1;
                        else if( hand.viewCard(j).getNumber() == 3)
                                cards[3] = cards[3] + 1;        
                        else if( hand.viewCard(j).getNumber() == 4)
                                cards[4] = cards[4] + 1;
                        else if( hand.viewCard(j).getNumber() == 5)
                                cards[5] = cards[5] + 1;
                        else if( hand.viewCard(j).getNumber() == 6)
                                cards[6] = cards[6] + 1;
                        else if( hand.viewCard(j).getNumber() == 7)
                                cards[7] = cards[7] + 1;
                        else if( hand.viewCard(j).getNumber() == 8)
                                cards[8] = cards[8] + 1;
                        else if( hand.viewCard(j).getNumber() == 9)
                                cards[9] = cards[9] + 1;
                        else if( hand.viewCard(j).getNumber() == 10)
                                cards[10] = cards[10] + 1;
                        else if( hand.viewCard(j).getNumber() == 11)
                                cards[11] = cards[11] + 1;
                        else if( hand.viewCard(j).getNumber() == 12)
                                cards[12] = cards[12] + 1;
                        else if( hand.viewCard(j).getNumber() == 13)
                                cards[13] = cards[13] + 1;              
                }
               
                // check each card value for an of-a-kind
                for(j=1; j<14; j++){
                        /// if 4 of a kidn
                        if( cards[j] == 4 ){
                                fourOfAKind = j;
                                if (j == 1)
                                        j = 14;
                                rating = 1470 + ( 14 * j);
                                System.out.println(  "  4 of a kind"  );
                                return rating;
                        }
                        // if first 3 of a kind (can be two pairs of 3 of a kind in 7)
                        else if( threeOfAKindA == 0 && cards[j] == 3 ){
                                threeOfAKindA = j;
                        }
                        // if first 2 of a kind (can be three pairs in 7 cards)
                        else if( twoOfAKindA == 0 && cards[j] == 2 ){
                                twoOfAKindA = j;
                        }
                        // for second 3 of a kinds , so we can find the better of the two
                        if( threeOfAKindA > 0 && threeOfAKindA != j && cards[j] == 3){
                                threeOfAKindTemp = j;
                        }
                        // this one cant be else bc there can be two two of a kinds or two and a 3 or three two of a kidns (in 7)
                        if ( twoOfAKindA > 0 && twoOfAKindA != j && twoOfAKindB == 0 && cards[j] == 2){
                                twoOfAKindB = j;
                        }
                        if ( twoOfAKindB > 0 && twoOfAKindB != j && cards[j] == 2){
                                        twoOfAKindTemp = j;
                        }
                       
                }
       
                // correct for Aces (in terms of rank)
                if(threeOfAKindA == 1)
                                threeOfAKindA = 14;
                if(threeOfAKindTemp == 1)
                                threeOfAKindTemp = 14;
                if(twoOfAKindA == 1)
                                twoOfAKindA = 14;
                if(twoOfAKindB == 1)
                                twoOfAKindB = 14;
                if(twoOfAKindTemp == 1)
                                twoOfAKindTemp = 14;
               
               
                // now choosing the best 3 of a kind , since u cant use two
                if ( threeOfAKindA != 0 && threeOfAKindTemp != 0 ){
                        // put hte biggest one in kindA
                        if(threeOfAKindTemp > threeOfAKindA)
                                threeOfAKindA = threeOfAKindTemp;
                }      


                // now placing the biggest two of a kind in A, second largest in B, third in Temp (temp wont be used)
                if(twoOfAKindTemp > twoOfAKindA){
                        swapKind = twoOfAKindA;
                        twoOfAKindA = twoOfAKindTemp;
                        twoOfAKindTemp = swapKind;
                }
                if(twoOfAKindTemp > twoOfAKindB){
                        swapKind = twoOfAKindB;
                        twoOfAKindB = twoOfAKindTemp;
                        twoOfAKindTemp = swapKind;
                }      
                // and make A biggest for full houses
                if(twoOfAKindB > twoOfAKindA){
                        swapKind = twoOfAKindA;
                        twoOfAKindA = twoOfAKindB;
                        twoOfAKindB = swapKind;
                }
                                       
               
               
                // check for full house
                if ( threeOfAKindA > 0 && twoOfAKindA >0 ){
                        rating = 1260 + (14 * threeOfAKindA) + twoOfAKindA;
                        System.out.println("  Full House"  );
                        return rating;
                }
               
               
                // flush, we alreayd know if there is a flush from above work but now we just get its highest card inside the flush
                if( flushSuit != 'z' ){
                        // now get highest of that suit for comparison with other flushes
                        for(int i = 0; i<7; i++){
                                // if ace
                                if(hand.viewCard(i).getSuit() == flushSuit && hand.viewCard(i).getNumber() == 1){
                                        rating = 1050 + (14 * 14);
                                        System.out.println("   Flush   ");
                                        return rating;
                                }
                                if(hand.viewCard(i).getSuit() == flushSuit && hand.viewCard(i).getNumber() > highCard){
                                        highCard = hand.viewCard(i).getNumber();
                                }
                        }
                        rating = 1050 + ( 14 * highCard) ;
                        System.out.println("   Flush   ");
                        return rating;
                }      
               
               
               
               
                //straight
                x=0;
                int cx = 0;
                for (x = 0; x<7; x++){
                        if(hand.viewCard(x).getSuit() != 'x'){
                                if (cx > 0){
                                        if (hand.viewCard(x).getNumber() != hand.viewCard(x-1).getNumber()){
                                                smallerHandB.receiveCard(hand.viewCard(x));
                                        }      
                                }
                                else if(cx == 0){
                                        smallerHandB.receiveCard(hand.viewCard(x));
                                }
                               
                        }
                        cx++;
                }
                count = 0;
                cardPtr = 0;
                straightCount = 1;      // count the first card
                initialCardValue = smallerHandB.viewCard(0).getNumber();
                while(count < 14){
                        if(cardPtr < smallerHandB.getAmountOfCards()-1){
                                if(smallerHandB.viewCard(cardPtr).getNumber() == smallerHandB.viewCard(cardPtr+1).getNumber()+1
                                                || smallerHandB.viewCard(cardPtr).getNumber() == 1 && smallerHandB.viewCard(cardPtr+1).getNumber() == 13)
                                        straightCount++;
                                else{
                                        straightCount = 1;
                                        initialCardValue = smallerHandB.viewCard(cardPtr+1).getNumber();
                                }
                                cardPtr++;
                        }      
                        else if(cardPtr == smallerHandB.getAmountOfCards()-1){  // for if we are at the last card in the hand
                                if(smallerHandB.viewCard(cardPtr).getNumber() == 2 && smallerHandB.viewCard(0).getNumber() == 1)
                                        straightCount++;
                                else{
                                        straightCount = 1;
                                        initialCardValue = smallerHandB.viewCard(0).getNumber();
                                }      
                                cardPtr=0;
                        }
                        if(straightCount == 5){
                                // we have a straight flush
                                rating = 840 + ( 14 * initialCardValue);
                                System.out.println("   Straight  ");
                                return rating;
                        }                              
                        count++;
                }
               
               
                // three of a kind
                if ( threeOfAKindA > 0 ){
                        rating = 630 + (14 * threeOfAKindA);
                        System.out.println("   3 of a kind  ");
                        return rating;
                }
               
                // two pair
                if (twoOfAKindA > 0 && twoOfAKindB > 0){
                        rating = 420 + (14 * twoOfAKindA) + twoOfAKindB;
                        System.out.println("   2 pair " );
                        return rating;
                }

                // one pair
                if(twoOfAKindA > 0){
                        rating = 210 + (14 * twoOfAKindA);
                        System.out.println("   one pair  ");
                        return rating;
                }
       
                // high card
                for(int i = 0; i<7; i++){
                        // if ace
                        if(hand.viewCard(i).getNumber() == 1){
                                rating = 14 * 14;
                                System.out.println("  High Card  ");
                                return rating;
                        }
                        if(hand.viewCard(i).getNumber() < highCard){
                                highCard = hand.viewCard(i).getNumber();
                        }
                }
                System.out.println("  High Card   ");
                rating = 14 * highCard;
                return rating;
        }
}
